<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>this的指向问题</title>
</head>
<body>
    
</body>
<script>
    var name = 222
    var a = {
        name: 111,
        say: function() {
            console.log(this.name)
        }
    }

    var fun = a.say
    fun() // 222
    a.say() // 111

    var b = {
        name: 333,
        say: function(fun) {
            fun() // 222
        }
    }
    b.say(a.say)
    b.say = a.say 
    b.say() // 333


    /* 函数中this的指向问题
        this和创建函数时没有关系，this的指向取决于谁最后调用这个函数
        分几种情况：
            1. 直接调用，this指向全局对象window
            2. 函数作为对象的属性被调用，this指向调用这个函数的对象
            3. 如果函数处于多级嵌套对象中，this指向调用这个函数的上一级对象。
                比如 window.a.b(), obj.a.b(),这两种情况b函数中this都是指向a对象
            4. 构造函数中this指向
                    a. 构造函数中无return
                        function Fn(){
                            this.num = 123
                        }
                        var a = new Fn()
                        console.log(a.num) // 123
                        这里之所以a可以点出Fn函数里的num，是因为new关键字可以改变this指向，new这个过程做了几件事：
                            1. 创建一个新对象
                            2. 新对象的__proto__指向构造函数的prototype（将this指向这个新对象）
                            3. 调用构造函数给新对象赋值
                            4. 返回新对象
                    b. 构造函数中有return
                        function Fn(){
                            this.num = 123
                            return {} 或者 
                            return function() {} 或者
                            return 1 或者
                            return undefined
                        }
                        var a = new Fn()
                        console.log(a.num) // undefined 或者 undefined 或者 123 或者 123
                        构造函数中如果返回值是一个对象，那么this指向的就是这个返回的对象；
                        如果返回的不是一个对象，那么this指向的还是函数的实例
        
        注意：严格版中this指向不再是window，而是undefined
    */ 

    /* 改变this指向
        1. call(改变this指向，实参，...)
            改变this指向后会自动调用该函数
        2. apply(改变this指向，实参数组)
            改变this指向后会自动调用该函数
        3. bind(改变this指向，实参，...)
            返回一个改变this指向后的新函数，需手动调用
    */
                   
    let a,b,c = 1
    function fn(a,b,c){
        console.log(this, a+b+c)
    }
    fn() // window, 3
    fn.call(document, 1,2,3) // document, 6
    fn.apply(document, [1,2,3]) // document, 6
    let func = fn.bind(document,1,2,3)
    func() // document, 6

</script>
</html>